#include "chess.h"
#include "math.h"
#include <string>
#include <iostream>
int Chess::get_x_index() const
{
    return x;
}
int Chess::get_y_index() const
{
    return y;
}
void Chess::set_index(int x_, int y_)
{
    x = x_;
    y = y_;
    moved = true;
}
Chess::chess_type Chess::get_type()
{
    return type;
}
std::string Chess::get_sig()
{
    return chessword[type][owner];
}
int Chess::get_owner()
{
    return owner;
}
bool Chess::get_moved()
{
    return moved;
}
int King::check_move(const std::vector<Chess *> &chesses, int targetx, int targety)
{
    if (x == targetx && x == targety)
    { //not move
        return 0;
    }
    bool flag_1 = false;
    for(auto chess : chesses){
        if(chess -> get_x_index() == targetx && chess -> get_y_index() == targety && chess ->get_type() == Chess::Rook){
            if(!chess->get_moved() && !moved){
                flag_1 = true;
            }
        }
    }
    if(flag_1)
    {
        int top = std::max(y,targety);
        int bottom = std::min(y,targety);
        for(auto chess : chesses)
        {
            if(chess->get_x_index() == x) {
                if (chess->get_y_index() < top && chess->get_y_index() > bottom) {
                    return 0;
                }
            }
        }
        return 3;
    }
    if (abs(targetx - x) > 1 || abs(targety - y) > 1)
    { //Mobile is too long
        return 0;
    }
    for (auto chess : chesses)
    {
        if (chess->get_x_index() == targetx && chess->get_y_index() == targety && chess->get_owner() == get_owner())
        { //You have your own pieces on the spot
            return 0;
        }
    }
    return 1;
}
int Queen::check_move(const std::vector<Chess *> &chesses, int targetx, int targety)
{
    if (x == targetx && x == targety)
    { //not move
        return 0;
    }
    if (((x + y) != (targetx + targety) && (x - y) != (targetx - targety)) && (abs(targetx - x) >= 1 && abs(targety - y) >= 1))
    { //Preliminary validation of sub-rule
        return 0;
    }
    //Judgment of a straight line
    bool flag = false; //Used to judge whether the end point is their piece
    if (targetx == x)
    {
        int low_ = std::min(y, targety);
        int high_ = std::max(y, targety);
        for (auto chess : chesses)
        { //Traverse the pieces
            if (chess->get_x_index() == x)
            { //Find pieces that might be in the path
                if (chess->get_y_index() == targety)
                { //There are pieces at the end
                    if (chess->get_owner() == get_owner())
                    {
                        return 0; //There are chess pieces on the side of the end, which are directly judged to be illegal movements
                    }
                    else
                    {
                        flag = true;
                    }
                }
                if (chess->get_y_index() < high_ && chess->get_y_index() > low_)
                { //There are pieces that appear on the path
                    return 0;
                }
            }
        }
        return flag ? 2 : 1;
    }
    if (targety == y)
    {
        int low_ = std::min(x, targetx);
        int high_ = std::max(x, targetx);
        for (auto chess : chesses)
        { //Traverse the pieces
            if (chess->get_y_index() == y)
            { //Discover pieces that may be on the path
                if (chess->get_x_index() == targetx)
                { //There are pieces at the finish line
                    if (chess->get_owner() == get_owner())
                    {
                        return 0; //There are chess pieces on the side of the end, which are directly judged to be illegal movements
                    }
                    else
                    {
                        flag = true;
                    }
                }
                if (chess->get_x_index() < high_ && chess->get_x_index() > low_)
                { //There are pieces that appear on the path
                    return 0;
                }
            }
        }
        return flag ? 2 : 1;
    }
    //Judgment of the slash
    flag = false;
    if (targetx + targety == x + y)
    {
        int low_ = std::min(y, targety);
        int high_ = std::max(y, targety);
        for (auto chess : chesses)
        { //Traverse the pieces
            if (chess->get_x_index() + chess->get_y_index() == x + y)
            { //Discover pieces that may be on the path
                if (chess->get_y_index() == targety)
                { //There are pieces at the finish line
                    if (chess->get_owner() == get_owner())
                    {
                        return 0; //There are chess pieces on the side of the end, which are directly judged to be illegal movements
                    }
                    else
                    {
                        flag = true;
                    }
                }
                if (chess->get_y_index() < high_ && chess->get_y_index() > low_)
                { //There are pieces that appear on the path
                    return 0;
                }
            }
        }
        return flag ? 2 : 1;
    }
    if (targetx - targety == x - y)
    {
        int low_ = std::min(y, targety);
        int high_ = std::max(y, targety);
        for (auto chess : chesses)
        { //Traverse the pieces
            if (chess->get_x_index() - chess->get_y_index() == x - y)
            { //Discover pieces that may be on the path
                if (chess->get_y_index() == targety)
                { //There are pieces at the finish line
                    if (chess->get_owner() == get_owner())
                    {
                        return 0; //There are chess pieces on the side of the end, which are directly judged to be illegal movements
                    }
                    else
                    {
                        flag = true;
                    }
                }
                if (chess->get_y_index() < high_ && chess->get_y_index() > low_)
                { //There are pieces that appear on the path
                    return 0;
                }
            }
        }
        return flag ? 2 : 1;
    }
}
int Knight::check_move(const std::vector<Chess *> &chesses, int targetx, int targety)
{
    if (x == targetx && x == targety)
    { //Do not move
        return 0;
    }
    if (x == targetx || y == targety)
    { //Preliminary validation of the walk rule
        return 0;
    }
    if (abs(targety - y) + abs(targetx - x) != 3)
    { //Verify the walk rule
        return 0;
    }
    for (auto chess : chesses)
    {
        if (chess->get_x_index() == targetx && chess->get_y_index() == targety)
        {
            return chess->get_owner() == owner ? 0 : 2;
        }
    }
    return 1;
}
int Rook::check_move(const std::vector<Chess *> &chesses, int targetx, int targety)
{
    if (x == targetx && y == targety)
    { //Not move
        return 0;
    }
    bool flag_1 = false;
    for(auto chess : chesses){
        if(chess -> get_x_index() == targetx && chess -> get_y_index() == targety && chess ->get_type() == Chess::King){
            if(!chess->get_moved() && !moved){
                flag_1 = true;
            }
        }
    }
    if(flag_1)
    {
        int top = std::max(y,targety);
        int bottom = std::min(y,targety);
        for(auto chess : chesses)
        {
            if(chess->get_x_index() == x) {
                if (chess->get_y_index() < top && chess->get_y_index() > bottom) {
                    return 0;
                }
            }
        }
        return 3;
    }
    if (abs(targetx - x) >= 1 && abs(targety - y) >= 1)
    { //Preliminary validation of the walk rule
        return 0;
    }
    bool flag = false; //Used to determine whether the end point is a pawn of its own side
    if (targetx == x)
    {
        int low_ = std::min(y, targety);
        int high_ = std::max(y, targety);
        for (auto chess : chesses)
        { //Traverse the pieces
            if (chess->get_x_index() == x)
            { //Discover pieces that may be on the path
                if (chess->get_y_index() == targety)
                { //There are pieces at the finish line
                    if (chess->get_owner() == get_owner())
                    {
                        return 0; //There are chess pieces on the side of the end, which are directly judged to be illegal movements
                    }
                    else
                    {
                        flag = true;
                    }
                }
                if (chess->get_y_index() < high_ && chess->get_y_index() > low_)
                { //There are pieces that appear on the path
                    return 0;
                }
            }
        }
    }
    if (targety == y)
    {
        int low_ = std::min(x, targetx);
        int high_ = std::max(x, targetx);
        for (auto chess : chesses)
        {
            if (chess->get_y_index() == y)
            {
                if (chess->get_x_index() == targetx)
                {
                    if (chess->get_owner() == get_owner())
                    {
                        return 0;
                    }
                    else
                    {
                        flag = true;
                    }
                }
                if (chess->get_x_index() < high_ && chess->get_x_index() > low_)
                {
                    return 0;
                }
            }
        }
    }
    return flag ? 2 : 1;
}
int Bishop::check_move(const std::vector<Chess *> &chesses, int targetx, int targety)
{
    if (x == targetx && x == targety)
    {
        return 0;
    }
    if ((x + y) != (targetx + targety) && (x - y) != (targetx - targety))
    { //Preliminary judgment on whether the move is legal
        return 0;
    }
    bool flag = false;
    if (targetx + targety == x + y)
    {
        int low_ = std::min(y, targety);
        int high_ = std::max(y, targety);
        for (auto chess : chesses)
        {
            if (chess->get_x_index() + chess->get_y_index() == x + y)
            {
                if (chess->get_y_index() == targety)
                {
                    if (chess->get_owner() == get_owner())
                    {
                        return 0;
                    }
                    else
                    {
                        flag = true;
                    }
                }
                if (chess->get_y_index() < high_ && chess->get_y_index() > low_)
                {
                    return 0;
                }
            }
        }
    }
    if (targetx - targety == x - y)
    {
        int low_ = std::min(y, targety);
        int high_ = std::max(y, targety);
        for (auto chess : chesses)
        {
            if (chess->get_x_index() - chess->get_y_index() == x - y)
            {
                if (chess->get_y_index() == targety)
                {
                    if (chess->get_owner() == get_owner())
                    {
                        return 0;
                    }
                    else
                    {
                        flag = true;
                    }
                }
                if (chess->get_y_index() < high_ && chess->get_y_index() > low_)
                {
                    return 0;
                }
            }
        }
    }
    return flag ? 2 : 1;
}
int Pawn::check_move(const std::vector<Chess *> &chesses, int targetx, int targety)
{
    int sig = owner ? -1 : 1;
    if (abs(targety - y) == 1 && x - targetx == 1 * sig)
    {//Angled chess
        for(auto chess : chesses)
        {
            if (chess->get_y_index() == targety && chess -> get_x_index() == targetx){
                if(owner != chess->get_owner())
                    return 2;
                else
                    return 0;
            }
        }
        for(auto chess : chesses)
        {
            if (chess->get_y_index() == targety && chess -> get_x_index() == x && owner != chess->get_owner() && x == (owner?4:5)){
                std::cout<<"qwq";
                return 4;
            }
        }
    }
    if (y != targety)
    { //Determine if it is on the same straight line
        return 0;
    }
    if (x - targetx != 1 * sig && !(!moved && x - targetx == 2 * sig))
    {
        return false;
    }
    if (abs(targetx - x) == 2)//Judge the situation where there is an obstacle in the middle of the jumping two blocks
    {
        int pos_x = (targetx + x) / 2;
        for (auto chess : chesses)
        {
            if (chess->get_y_index() == targety && chess->get_x_index() == pos_x)
            {
                return 0;
            }
        }
    }
    for (auto chess : chesses)
    {
        if (chess->get_y_index() == targety && chess->get_x_index() == targetx)
        {
            return 0;
        }
    }
    if(targetx == 1 || targetx == 8){
        return 5;
    }
    return 1;
}